﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;

namespace iNet.Tasks
{
	/// <summary>
	/// 工作執行器。
	/// </summary>
	public class TaskExecutor : IDisposable
	{
		#region 欄位
		static TaskExecutor _DefaultExecutor;
		readonly Timer _DelayedTaskCheckTimer;
		readonly LinkedList<Task> _DelayedTasks = new LinkedList<Task>();
		bool _Disposed;
		volatile ApartmentState _ExecutionThreadApartmentState = ApartmentState.MTA;
		volatile TaskExecutionThreadMode _ExecutionThreadMode = TaskExecutionThreadMode.OnDemand;
		readonly LinkedList<Task> _HighPriorityTasks = new LinkedList<Task>();
		bool _IsBackground;
		volatile bool _IsDebugLogEnabled;
		readonly LinkedList<Task> _LowPriorityTasks = new LinkedList<Task>();
		volatile int _MaxThreads = 1;
		readonly string _Name;
		volatile int _NumberOfReadyTasks;
		volatile int _NumberOfWaitingThreads;
		readonly LinkedList<Task> _NormalPriorityTasks = new LinkedList<Task>();
		readonly object _SyncRoot = new object();
		readonly SemaphoreSlim _TaskQueueSemaphore = new SemaphoreSlim(0);
		readonly List<TaskExecutionThread> _Threads = new List<TaskExecutionThread>();
		#endregion
		#region 型別建構子
		static TaskExecutor()
		{
			_DefaultExecutor = new TaskExecutor(true);
			_DefaultExecutor.MaxThreads = (Environment.ProcessorCount + 1);
		}
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		public TaskExecutor()
			: this(true)
		{ }
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		/// <param name="name">執行器名稱。</param>
		public TaskExecutor(string name)
			: this(true)
		{
			_Name = name;
		}
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		/// <param name="isBackground">是否為背景執行。</param>
		public TaskExecutor(bool isBackground)
			: this(null, isBackground)
		{ }
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		/// <param name="name">執行器名稱。</param>
		/// <param name="isBackground">是否為背景執行。</param>
		public TaskExecutor(string name, bool isBackground)
		{
			//初始化欄位
			_IsBackground = isBackground;
			_Name = name;

			//建立計時器
			_DelayedTaskCheckTimer = new Timer((state) =>
			{
				this.CheckDelayedTasks();
			});
		}
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		/// <param name="isBackground">是否為背景執行。</param>
		/// <param name="maxThreads">最多用於執行工作的執行緒數量。</param>
		/// <exception cref="ArgumentOutOfRangeException">maxThreads 小於或等於零。</exception>
		public TaskExecutor(bool isBackground, int maxThreads)
			: this(null, isBackground, maxThreads)
		{ }
		/// <summary>
		/// 初始化新的 TaskExecutor 執行個體。
		/// </summary>
		/// <param name="name">執行器名稱。</param>
		/// <param name="isBackground">是否為背景執行。</param>
		/// <param name="maxThreads">最多用於執行工作的執行緒數量。</param>
		/// <exception cref="ArgumentOutOfRangeException">maxThreads 小於或等於零。</exception>
		public TaskExecutor(string name, bool isBackground, int maxThreads)
			: this(isBackground)
		{
			if (maxThreads <= 0)
				throw new ArgumentOutOfRangeException();
			_MaxThreads = maxThreads;
			_Name = name;
		}
		#endregion
		#region CancelAllTasks
		/// <summary>
		/// 取消所有工作的執行。
		/// </summary>
		public void CancelAllTasks()
		{
			lock (_SyncRoot)
			{
				//確認狀態
				if (_Disposed)
					throw new InvalidOperationException();

				//清空佇列
				if (_IsDebugLogEnabled)
					this.WriteDebugLog("Cancel all tasks");
				if (_NumberOfReadyTasks > 0)
				{
					//清空佇列
					_LowPriorityTasks.Clear();
					_NormalPriorityTasks.Clear();
					_HighPriorityTasks.Clear();
					_DelayedTasks.Clear();
					_NumberOfReadyTasks = 0;

					//停止計時
					_DelayedTaskCheckTimer.Change(Timeout.Infinite, Timeout.Infinite);

					//引發事件
					this.ReadyTaskCountChanged.RaiseEvent(this, EventArgs.Empty);
				}

				//取消正在執行的工作
				for (int i = _Threads.Count - 1; i >= 0; --i)
				{
					Task task = _Threads[i].CurrentTask;
					if (task != null)
						task.CancelInternal(false);
				}
			}
		}
		#endregion
		#region CancelTask
		/// <summary>
		/// 取消工作的執行。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		public void CancelTask(Task task)
		{
			this.CancelTask(task, false);
		}
		bool CancelTask(Task task, bool reset)
		{
			//確認
			if (task == null)
				throw new ArgumentNullException("task");

			//取消工作
			lock (_SyncRoot)
			{
				//確認狀態
				if (_Disposed)
					throw new InvalidOperationException();

				//確認是否屬於本執行器
				if (task.Executor != this)
					return false;

				//從佇列中移除
				if (task.TaskQueueNode.List != null)
				{
					//從佇列中移除
					task.TaskQueueNode.List.Remove(task.TaskQueueNode);
					--_NumberOfReadyTasks;
					if (_IsDebugLogEnabled)
						this.WriteDebugLog("Cancel task '{0}' ({1}), ready task count : {2}", task.Name, task.GetHashCode(), _NumberOfReadyTasks);

					//更新計時器
					if (task.ReadyTime != null)
						this.CheckDelayedTasks();

					//引發事件
					this.ReadyTaskCountChanged.RaiseEvent(this, EventArgs.Empty);
				}

				//取消工作
				task.CancelInternal(reset);

				//完成
				return true;
			}
		}
		#endregion
		#region CancelTasks
		/// <summary>
		/// 取消所有符合條件的工作。
		/// </summary>
		/// <param name="predicate">判斷工作是否符合條件的方法。</param>
		/// <returns>取消的工作數量。</returns>
		/// <exception cref="ArgumentNullException">predicate 為 Null (Visual Basic 為 Nothing)。</exception>
		public int CancelTasks(Predicate<Task> predicate)
		{
			//確認參數
			if (predicate == null)
				throw new ArgumentNullException("predicate");

			//取消工作
			int count;
			lock (_SyncRoot)
			{
				//取消等待的工作
				count = this.DequeueTasks(predicate);

				//取消執行中的工作
				for (int i = _Threads.Count - 1; i >= 0; --i)
				{
					Task task = _Threads[i].CurrentTask;
					if (task != null)
					{
						task.CancelInternal(false);
						++count;
					}
				}
			}
			return count;
		}
		#endregion
		#region CheckDelayedTasks
		void CheckDelayedTasks()
		{
			lock (_SyncRoot)
			{
				while (_DelayedTasks.Count > 0)
				{
					//計算時間
					long firstReadyTime = _DelayedTasks.First.Value.ReadyTime.Value;
					long checkTime = (firstReadyTime - (long)(DateTime.Now - DateTime.MinValue).TotalMilliseconds);
					if (checkTime > 0)
					{
						_DelayedTaskCheckTimer.Change(checkTime, Timeout.Infinite);
						return;
					}

					//將工作加入至佇列
					Task task = _DelayedTasks.First.Value;
					_DelayedTasks.RemoveFirst();
					LinkedList<Task> taskQueue;
					switch (task.Priority)
					{
						case TaskPriority.Normal:
							taskQueue = _NormalPriorityTasks;
							break;
						case TaskPriority.High:
							taskQueue = _HighPriorityTasks;
							break;
						case TaskPriority.Low:
							taskQueue = _LowPriorityTasks;
							break;
						default:
							throw new ArgumentException();
					}
					taskQueue.AddFirst(task.TaskQueueNode);

					//執行工作
					_TaskQueueSemaphore.Release();
					this.UpdateThreads();
				}
			}
		}
		#endregion
		#region DefaultExecutor
		/// <summary>
		/// 取得全域的工作執行器。
		/// </summary>
		public static TaskExecutor DefaultExecutor
		{
			get
			{
				return _DefaultExecutor;
			}
		}
		#endregion
		#region DequeueTask
		/// <summary>
		/// 將指定的工作從等待佇列中移除。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <returns>True 表示工作移除成功，False 表示工作已開始執行 -或- 工作已執行完成 -或- 工作不屬於此執行器。</returns>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		public bool DequeueTask(Task task)
		{
			//確認參數
			if (task == null)
				throw new ArgumentNullException("task");

			//將工作從佇列中移除
			lock (_SyncRoot)
			{
				//取消工作
				if (!this.CancelTask(task, true))
					return false;

				//完成
				return (task.State == TaskState.Initializing);
			}
		}
		Task DequeueTask(TaskPriority? minPriority)
		{
			lock (_SyncRoot)
			{
				//搜尋非空佇列
				int minPriorityValue = (minPriority == null ? int.MaxValue : (int)minPriority.Value);
				LinkedList<Task> queue;
				if (_HighPriorityTasks.Count > 0 && minPriorityValue >= (int)TaskPriority.High)
					queue = _HighPriorityTasks;
				else if (_NormalPriorityTasks.Count > 0 && minPriorityValue >= (int)TaskPriority.Normal)
					queue = _NormalPriorityTasks;
				else if (_LowPriorityTasks.Count > 0 && minPriorityValue >= (int)TaskPriority.Low)
					queue = _LowPriorityTasks;
				else
				{
					//if (minPriority != null && _NumberOfReadyTasks > 0)
						//_TaskQueueSemaphore.Release();
					return null;
				}

				//從佇列中取出
				--_NumberOfReadyTasks;
				Task task = queue.First.Value;
				queue.RemoveFirst();

				//引發事件
				this.ReadyTaskCountChanged.RaiseEvent(this, EventArgs.Empty);

				//回傳
				return task;
			}
		}
		#endregion
		#region DequeueTasks
		/// <summary>
		/// 將所有符合條件的工作從等待佇列中移除。
		/// </summary>
		/// <param name="predicate">判斷工作是否符合條件的方法。</param>
		/// <returns>移除的工作數量。</returns>
		/// <exception cref="ArgumentNullException">predicate 為 Null (Visual Basic 為 Nothing)。</exception>
		public int DequeueTasks(Predicate<Task> predicate)
		{
			//確認參數
			if (predicate == null)
				throw new ArgumentNullException("predicate");

			//取消工作
			int count = 0;
			lock (_SyncRoot)
			{
				//取消等待的工作
				count += this.DequeueTasks(_LowPriorityTasks, predicate);
				count += this.DequeueTasks(_NormalPriorityTasks, predicate);
				count += this.DequeueTasks(_HighPriorityTasks, predicate);

				//引發事件
				if (count > 0)
					this.ReadyTaskCountChanged.RaiseEvent(this, EventArgs.Empty);
			}
			return count;
		}
		int DequeueTasks(LinkedList<Task> queue, Predicate<Task> predicate)
		{
			int count = 0;
			LinkedListNode<Task> node = queue.First;
			while (node != null)
			{
				//記錄下一個工作
				LinkedListNode<Task> nextNode = node.Next;

				//確認並移除工作
				Task task = node.Value;
				if (predicate(task))
				{
					task.CancelInternal(true);
					queue.Remove(node);
					--_NumberOfReadyTasks;
				}

				//移至下一個工作
				node = nextNode;
			}
			return count;
		}
		#endregion
		#region Dispose
		/// <summary>
		/// 關閉執行器並釋放使用的資源。
		/// </summary>
		public void Dispose()
		{
			lock (_SyncRoot)
			{
				//確認狀態
				if (_Disposed)
					return;

				//取消所有工作
				this.CancelAllTasks();

				//標示已關閉
				_Disposed = true;

				//關閉所有執行緒
				this.UpdateThreads();
			}
		}
		#endregion
		#region EnqueueTask
		/// <summary>
		/// 將指定的工作加入佇列準備執行。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <param name="enqueueToFrontOfQueue">是否要加入於佇列的最前端，預設值為 False。</param>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">task 的狀態不是 Initializing。</exception>
		public void EnqueueTask(Task task, bool enqueueToFrontOfQueue = false)
		{
			//確認
			if (task == null)
				throw new ArgumentNullException("task");

			//加入佇列
			lock (_SyncRoot)
			{
				//確認狀態
				if (_Disposed)
					throw new InvalidOperationException();

				//設定 Executor
				task.SetExecutor(this);

				//準備執行工作
				task.Ready();

				//加入佇列
				long? readyTime = task.ReadyTime;
				if (readyTime == null)
				{
					LinkedList<Task> taskQueue;
					switch (task.Priority)
					{
						case TaskPriority.Normal:
							taskQueue = _NormalPriorityTasks;
							break;
						case TaskPriority.High:
							taskQueue = _HighPriorityTasks;
							break;
						case TaskPriority.Low:
							taskQueue = _LowPriorityTasks;
							break;
						default:
							throw new ArgumentException();
					}
					if (task.ParentTask != null || enqueueToFrontOfQueue)
						taskQueue.AddFirst(task.TaskQueueNode);
					else
						taskQueue.AddLast(task.TaskQueueNode);
				}
				else
				{
					long readyTimeValue = readyTime.Value;
					LinkedListNode<Task> prevNode = _DelayedTasks.First;
					while (prevNode != null)
					{
						long nextReadyTimeValue = prevNode.Value.ReadyTime.Value;
						if (nextReadyTimeValue > readyTimeValue || (nextReadyTimeValue == readyTimeValue && enqueueToFrontOfQueue))
						{
							prevNode = prevNode.Previous;
							break;
						}
						prevNode = prevNode.Next;
					}
					if (prevNode == null)
						_DelayedTasks.AddFirst(task.TaskQueueNode);
					else
						_DelayedTasks.AddAfter(prevNode, task.TaskQueueNode);
				}
				++_NumberOfReadyTasks;
				if (_IsDebugLogEnabled)
					this.WriteDebugLog("Enqueue task '{0}' ({1}), priority : {2}, ready task count : {3}", task.Name, task.GetHashCode(), task.Priority, _NumberOfReadyTasks);

				//引發事件
				this.ReadyTaskCountChanged.RaiseEvent(this, EventArgs.Empty);

				//執行工作
				if (readyTime == null)
				{
					//啟動執行緒執行工作
					_TaskQueueSemaphore.Release();

					//建立執行緒
					this.UpdateThreads();
				}
				else
					this.CheckDelayedTasks();
			}
		}
		#endregion
		#region EnqueueTaskAndWait
		/// <summary>
		/// 將指定的工作加入佇列準備執行，並等待其執行完成。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <param name="enqueueToFrontOfQueue">是否要加入於佇列的最前端，預設值為 False。</param>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">task 的狀態不是 Initializing。</exception>
		public void EnqueueTaskAndWait(Task task, bool enqueueToFrontOfQueue = false)
		{
			this.EnqueueTaskAndWait(task, Timeout.Infinite, enqueueToFrontOfQueue);
		}
		/// <summary>
		/// 將指定的工作加入佇列準備執行，並等待其執行完成。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <param name="timeout">等待的逾時長度，單位為毫秒。</param>
		/// <param name="enqueueToFrontOfQueue">是否要加入於佇列的最前端，預設值為 False。</param>
		/// <returns>True 表示工作在指定的時間內完成，False 表示等待逾時。</returns>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">task 的狀態不是 Initializing。</exception>
		public bool EnqueueTaskAndWait(Task task, int timeout, bool enqueueToFrontOfQueue = false)
		{
			//開始工作
			this.EnqueueTask(task, enqueueToFrontOfQueue);

			//等待完成
			return task.WaitForCompletion(timeout);
		}
		#endregion
		#region ExecutionThreadApartmentState
		/// <summary>
		/// 取得或設定工作執行緒的 Apartment 狀態，預設值為 ApartmentState.MTA。
		/// </summary>
		public ApartmentState ExecutionThreadApartmentState
		{
			get
			{
				return _ExecutionThreadApartmentState;
			}
			set
			{
				if (!value.IsDefined() || value == ApartmentState.Unknown)
					throw new ArgumentException();
				_ExecutionThreadApartmentState = value;
			}
		}
		#endregion
		#region ExecutionThreadMode
		/// <summary>
		/// 取得或設定執行緒模式，預設值為 TaskExecutionThreadMode.OnDemand。
		/// </summary>
		public TaskExecutionThreadMode ExecutionThreadMode
		{
			get
			{
				return _ExecutionThreadMode;
			}
			set
			{
				if (!value.IsDefined())
					throw new ArgumentException();
				lock (_SyncRoot)
				{
					if (_ExecutionThreadMode == value)
						return;
					_ExecutionThreadMode = value;
				}
				lock (_TaskQueueSemaphore)
				{
					if (value == TaskExecutionThreadMode.OnDemand && _NumberOfWaitingThreads > 0)
						_TaskQueueSemaphore.Release(_NumberOfWaitingThreads);
				}
			}
		}
		#endregion
		#region GetHigherPriority
		internal static TaskPriority GetHigherPriority(TaskPriority priority)
		{
			switch (priority)
			{
				case TaskPriority.Normal:
					return TaskPriority.High;
				case TaskPriority.Low:
					return TaskPriority.Normal;
				default:
					return TaskPriority.High;
			}
		}
		#endregion
		#region GetNextTask
		internal Task GetNextTask(bool waitForTask, TaskPriority? minPriority)
		{
			//計算等待時間
			int timeout = (waitForTask ? (_ExecutionThreadMode == TaskExecutionThreadMode.OnDemand ? 5000 : Timeout.Infinite) : 0);
			if (_IsDebugLogEnabled && timeout != 0)
				this.WriteDebugLog("Start get task for '{0}' in {1} ms", Thread.CurrentThread.Name, timeout);

			//取得工作
			Stopwatch watch = (timeout != Timeout.Infinite && timeout != 0 ? new Stopwatch() : null);
			while (true)
			{
				//等待
				if (watch != null)
					watch.Restart();
				lock (_TaskQueueSemaphore)
				{
					++_NumberOfWaitingThreads;
				}
				if (!_TaskQueueSemaphore.Wait(timeout))
				{
					lock (_TaskQueueSemaphore)
					{
						--_NumberOfWaitingThreads;
					}
					if (_IsDebugLogEnabled && timeout != 0)
						this.WriteDebugLog("Cannot get task for '{0}' in {1} ms", Thread.CurrentThread.Name, timeout);
					return null;
				}
				if (watch != null)
				{
					watch.Stop();
					timeout -= (int)watch.ElapsedMilliseconds;
					if (timeout < 0)
						timeout = 0;
				}
				lock (_TaskQueueSemaphore)
				{
					--_NumberOfWaitingThreads;
				}

				//取得工作
				lock (_SyncRoot)
				{
					Task task = this.DequeueTask(minPriority);
					if (task == null)
					{
						if (_NumberOfReadyTasks > 0)
							_TaskQueueSemaphore.Release();
						if (timeout == Timeout.Infinite || timeout > 0)
							continue;
						if (_IsDebugLogEnabled)
							this.WriteDebugLog("Cannot get task for '{0}'", Thread.CurrentThread.Name);
						return null;
					}
					if (task != null && _IsDebugLogEnabled)
						this.WriteDebugLog("Dequeue task '{0}' ({1}) by '{2}', ready task count : {3}", task.Name, task.GetHashCode(), Thread.CurrentThread.Name, _NumberOfReadyTasks);
					return task;
				}
			}
		}
		#endregion
		#region InvokeAsync
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <param name="args">呼叫方法所傳入的參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync(Delegate method, params object[] args)
		{
			return this.InvokeAsync(TaskPriority.Normal, method, args);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync(Action method)
		{
			return this.InvokeAsync(TaskPriority.Normal, (Delegate)method);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1>(Action<TArg1> method, TArg1 arg1)
		{
			return this.InvokeAsync(TaskPriority.Normal, (Delegate)method, arg1);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <param name="arg2">呼叫方法的第二個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1, TArg2>(Action<TArg1, TArg2> method, TArg1 arg1, TArg2 arg2)
		{
			return this.InvokeAsync(TaskPriority.Normal, (Delegate)method, arg1, arg2);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TOut>(Func<TOut> method)
		{
			return this.InvokeAsync(TaskPriority.Normal, (Delegate)method);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1, TOut>(Func<TArg1, TOut> method, TArg1 arg1)
		{
			return this.InvokeAsync(TaskPriority.Normal, (Delegate)method, arg1);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync(TaskPriority priority, Action method)
		{
			return this.InvokeAsync(priority, (Delegate)method);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1>(TaskPriority priority, Action<TArg1> method, TArg1 arg1)
		{
			return this.InvokeAsync(priority, (Delegate)method, arg1);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <param name="arg2">呼叫方法的第二個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1, TArg2>(TaskPriority priority, Action<TArg1, TArg2> method, TArg1 arg1, TArg2 arg2)
		{
			return this.InvokeAsync(priority, (Delegate)method, arg1, arg2);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TOut>(TaskPriority priority, Func<TOut> method)
		{
			return this.InvokeAsync(priority, (Delegate)method);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <param name="arg1">呼叫方法的第一個參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync<TArg1, TOut>(TaskPriority priority, Func<TArg1, TOut> method, TArg1 arg1)
		{
			return this.InvokeAsync(priority, (Delegate)method, arg1);
		}
		/// <summary>
		/// 非同步呼叫指定的方法。
		/// </summary>
		/// <param name="priority">非同步呼叫的優先權。</param>
		/// <param name="method">指定的方法。</param>
		/// <param name="args">呼叫方法所傳入的參數。</param>
		/// <returns>表示非同步呼叫的 CallbackTask。</returns>
		/// <exception cref="ArgumentException">priority 參數值無效。</exception>
		/// <exception cref="ArgumentNullException">method 為 Null (Visual Basic 為 Nothing)。</exception>
		public CallbackTask InvokeAsync(TaskPriority priority, Delegate method, params object[] args)
		{
			//確認參數
			if (!priority.IsDefined())
				throw new ArgumentException();
			if (method == null)
				throw new ArgumentNullException("method");

			//建立工作
			CallbackTask task = new CallbackTask(method, args);
			task.Priority = priority;

			//開始工作
			this.EnqueueTask(task);

			//回傳
			return task;
		}
		#endregion
		#region IsBackground
		/// <summary>
		/// 取得是否使用背景執行。
		/// </summary>
		public bool IsBackground
		{
			get
			{
				return _IsBackground;
			}
		}
		#endregion
		#region IsDebugLogEnabled
		/// <summary>
		/// 取得或設定是否需輸出偵錯訊息，預設值為 False。
		/// </summary>
		public bool IsDebugLogEnabled
		{
			get
			{
				return _IsDebugLogEnabled;
			}
			set
			{
				_IsDebugLogEnabled = value;
			}
		}
		#endregion
		#region MaxThreads
		/// <summary>
		/// 取得或設定最多用於執行工作的執行緒數量，預設值為 1。
		/// </summary>
		public int MaxThreads
		{
			get
			{
				return _MaxThreads;
			}
			set
			{
				//確認參數
				if (value < 1)
					throw new ArgumentOutOfRangeException();

				//變更執行緒數量
				lock (_SyncRoot)
				{
					//確認狀態
					if (_Disposed)
						throw new InvalidOperationException();

					//確認參數
					if (_MaxThreads == value)
						return;

					//變更執行緒數量
					_MaxThreads = value;
					this.UpdateThreads();
				}
			}
		}
		#endregion
		#region MoveTaskToFrontOfQueue
		/// <summary>
		/// 將指定的工作移至佇列最前端。
		/// </summary>
		/// <param name="task">指定的工作。</param>
		/// <returns>True 表示移動成功，False 表示工作已經開始執行 -或- 工作已完成。</returns>
		/// <exception cref="ArgumentNullException">task 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">執行器已經處置。</exception>
		public bool MoveTaskToFrontOfQueue(Task task)
		{
			//確認參數
			if (task == null)
				throw new ArgumentNullException("task");

			//變更工作在佇列中的位置
			lock (_SyncRoot)
			{
				//確認狀態
				if (_Disposed)
					throw new InvalidOperationException();

				//確認是否屬於本執行器
				if (task.Executor != this)
					return false;

				//變更工作在佇列中的位置
				LinkedList<Task> queue = task.TaskQueueNode.List;
				if (queue != null)
				{
					queue.Remove(task.TaskQueueNode);
					queue.AddFirst(task.TaskQueueNode);
				}

				//完成
				return true;
			}
		}
		#endregion
		#region Name
		/// <summary>
		/// 取得工作執行器的名稱。
		/// </summary>
		public string Name
		{
			get
			{
				return _Name;
			}
		}
		#endregion
		#region RaiseExecutingTask
		internal void RaiseExecutingTask(TaskEventArgs e)
		{
			this.ExecutingTask.RaiseEvent<TaskEventArgs>(this, e);
		}
		#endregion
		#region RaiseTaskExecuted
		internal void RaiseTaskExecuted(TaskEventArgs e)
		{
			this.TaskExecuted.RaiseEvent<TaskEventArgs>(this, e);
		}
		#endregion
		#region ReadyTaskCount
		/// <summary>
		/// 取得佇列中等待執行的工作數量。
		/// </summary>
		public int ReadyTaskCount
		{
			get
			{
				return _NumberOfReadyTasks;
			}
		}
		#endregion
		#region RemoveThread
		internal void RemoveThread(TaskExecutionThread thread)
		{
			lock (_SyncRoot)
			{
				_Threads.Remove(thread);
			}
		}
		#endregion
		#region UpdateThreads
		internal void UpdateThreads()
		{
			bool abortAllThreads = false;
			try
			{
				lock (_SyncRoot)
				{
					//關閉所有執行緒
					if (_Disposed)
					{
						for (int i = _Threads.Count - 1; i >= 0; --i)
							_Threads[i].Abort();
						abortAllThreads = true;
						return;
					}

					//統計可用的執行緒
					int numOfAvailableThreads = 0;
					for (int i = _Threads.Count - 1; i >= 0; --i)
					{
						if (!_Threads[i].IsAborting)
							++numOfAvailableThreads;
					}

					//關閉多餘的執行緒
					for (int i = _Threads.Count - 1; i >= 0 && numOfAvailableThreads > _MaxThreads; --i)
					{
						TaskExecutionThread thread = _Threads[i];
						if (!thread.IsAborting)
						{
							thread.Abort();
							--numOfAvailableThreads;
						}
					}

					//增加執行緒
					if (numOfAvailableThreads < _MaxThreads)
					{
						int numOfNewThreads = Math.Min((_NumberOfReadyTasks - _DelayedTasks.Count), _MaxThreads - numOfAvailableThreads);
						for (; numOfNewThreads > 0; --numOfNewThreads)
							_Threads.Add(new TaskExecutionThread(this, _IsBackground));
					}
				}
			}
			finally
			{
				//關閉所有執行緒
				if (abortAllThreads)
				{
					lock (_TaskQueueSemaphore)
					{
						if (_NumberOfWaitingThreads > 0)
							_TaskQueueSemaphore.Release(_NumberOfWaitingThreads);
					}
				}
			}
		}
		#endregion
		#region WriteDebugLog
		internal void WriteDebugLog(string message)
		{
			Debug.WriteLine("[TaskExecutor][" + _Name + "] " + message);
		}
		internal void WriteDebugLog(string format, params object[] args)
		{
			Debug.WriteLine("[TaskExecutor][" + _Name + "] " + string.Format(format, args));
		}
		#endregion
		#region 事件
		/// <summary>
		/// 發生在開始執行工作前。
		/// </summary>
		public event EventHandler<TaskEventArgs> ExecutingTask;
		/// <summary>
		/// 發生在佇列中的工作數量改變後。
		/// </summary>
		public event EventHandler ReadyTaskCountChanged;
		/// <summary>
		/// 發生在工作執行完成後。
		/// </summary>
		public event EventHandler<TaskEventArgs> TaskExecuted;
		#endregion
	}
}
